package jp.ddo.trismegistos.framework.service;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import jp.ddo.trismegistos.framework.util.ClassUtil;

public abstract class Service {

	private Connection con;

	protected PreparedStatement createSql(final String sql) throws SQLException {
		return con.prepareStatement(sql);
	}

	protected int exec(final PreparedStatement ps) throws SQLException {
		final int count = ps.executeUpdate();
		ps.close();
		return count;
	}

	protected <T> T get(final PreparedStatement ps, final Class<T> resultClass)
			throws SQLException {

		final ResultSet rs = ps.executeQuery();
		try {
			if (rs.next()) {
				return convert(rs, resultClass);
			} else {
				return null;
			}
		} finally {
			rs.close();
			ps.close();
		}
	}

	protected <T> List<T> getList(final PreparedStatement ps,
			final Class<T> resultClass) throws SQLException {

		final List<T> list = new ArrayList<T>();
		final ResultSet rs = ps.executeQuery();

		try {
			while (rs.next()) {
				list.add(convert(rs, resultClass));
			}
		} finally {
			rs.close();
			ps.close();
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	protected <T> T convert(final ResultSet rs, final Class<T> resultClass) {
		final Object clazz = ClassUtil.newInstance(resultClass);
		for (final Field f : clazz.getClass().getDeclaredFields()) {
			f.setAccessible(true);
			final String name = f.getName();
			try {
				f.set(clazz, rs.getObject(fieldToConst(name)));
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (final SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return (T) clazz;
	}

	protected int getInt(final PreparedStatement ps) throws SQLException {
		final ResultSet rs = ps.executeQuery();
		try {
			if (rs.next()) {
				return rs.getInt(1);
			} else {
				return 0;
			}
		} finally {
			rs.close();
			ps.close();
		}
	}

	protected String fieldToConst(final String str) {
		final StringBuilder sb = new StringBuilder();

		for (int i = 0; i < str.length(); i++) {
			final String c = str.substring(i, i + 1);
			final String uc = c.toUpperCase();
			if (c.equals(uc) == false) {
				// 小文字は大文字にしてappend
				sb.append(uc);
			} else {
				sb.append("_");
				sb.append(uc);
			}
		}
		return sb.toString();
	}

	public void setConnection(final Connection con) {
		this.con = con;
	}
}
